#pragma once
#include "CardRange.h"
#include <unordered_map>

/// \brief 哈希函数用于手牌数组的无序映射
struct HandHash {
    size_t operator()(const std::array<uint8_t, 2>& hand) const {
        uint8_t a = std::min(hand[0], hand[1]);
        uint8_t b = std::max(hand[0], hand[1]);
        return a * 256 + b; // 组合两个uint8_t为一个哈希值
    }};

/// \brief 带权重的手牌范围类，支持按权重随机采样

#include <vector>
#include <array>
#include <string>
#include <random>
#include <utility>
#include <mutex> 
using namespace std;

namespace omp {

class WeightedCardRange {
public:
    // 构造函数，支持如 "QQ+:0.5,JJ:0.25,99:0.25"
    WeightedCardRange(const std::string& expr, bool normalize = true, bool debugOutput = false);

   // 添加拷贝构造函数声明
    /// \brief 拷贝构造函数
    /// \param other 要拷贝的WeightedCardRange对象
    WeightedCardRange(const WeightedCardRange& other);

    // WeightedCardRange(const WeightedCardRange& other) = delete; 
    WeightedCardRange& operator=(const WeightedCardRange& other) = delete;
    
    // 手动实现移动构造函数和移动赋值操作符
    /// \brief 移动构造函数
    /// \param other 要移动的WeightedCardRange对象
    WeightedCardRange(WeightedCardRange&& other) noexcept
        : mWeightedCombos(std::move(other.mWeightedCombos)), 
          mOriginalHandStrings(std::move(other.mOriginalHandStrings)),
          mRng(std::move(other.mRng)), 
          mDist(std::move(other.mDist)), 
          mWeightMap(std::move(other.mWeightMap))
          {}
    /// \brief 移动赋值操作符
    /// \param other 要移动的WeightedCardRange对象
    WeightedCardRange& operator=(WeightedCardRange&& other) noexcept {
        if (this != &other) {
            mWeightedCombos = std::move(other.mWeightedCombos);
            mOriginalHandStrings = std::move(other.mOriginalHandStrings);
            mWeightMap = std::move(other.mWeightMap);
            mRng = std::move(other.mRng);
            mDist = std::move(other.mDist);
        }
        return *this;
    }

    // 将手牌范围转换为字符串表达形式
    string toString() const;

    // 获取所有带权重的组合
    const vector<pair<array<uint8_t,2>, double>>& getWeightedCombos() const { 
        return mWeightedCombos; 
    }

    // 获取特定手牌的原始字符串表示
    const string& getOriginalHandString(const array<uint8_t,2>& hand) const {
        auto it = mOriginalHandStrings.find(hand);
        if (it != mOriginalHandStrings.end()) {
            return it->second;
        } else {
            static const string empty = "";
            return empty;
        }
    }

    // 按权重随机抽取一组手牌（一次抽取）
    array<uint8_t,2> sample() const;

    // 查询某手牌组合的权重
    double weight(const std::array<uint8_t,2>& hand) const;

private:
    bool mDebugOutput;
    std::vector<std::pair<std::array<uint8_t,2>, double>> mWeightedCombos;
    std::unordered_map<std::array<uint8_t, 2>, std::string, HandHash> mOriginalHandStrings; // 存储原始手牌字符串表示
    mutable std::mt19937 mRng; // 随机数生成器
    mutable std::uniform_real_distribution<double> mDist; // 均匀分布
    std::unordered_map<std::array<uint8_t, 2>, double, HandHash> mWeightMap; // 手牌权重快速查找表

    // 新增：复制函数
    WeightedCardRange copy() const {
        return WeightedCardRange(toString(), false);
    }


};
}